﻿using PerpheralDevice.IRepository;

namespace PerpheralDevice;

/// <summary>
/// 外部设备
/// </summary>
public abstract class PerpDev {
    /// <summary>
    /// 是否 仿真外设 服务(如果对应外设没有初始化成功，则会设置IsMocking为True)
    /// </summary>
    public bool IsMocking{ get; protected set; }
    protected PerpDev() { }
    /// <summary>
    /// 外设ID
    /// </summary>
    public string PerpDevID { get; protected set; }
    /// <summary>
    /// 外设名称
    /// </summary>
    public string PerpDevName { get; protected set; }
    protected readonly List<PerpDevUnit> mfPerpDevUnitList = [];

    /// <summary>
    /// 外设的初始化
    /// </summary>
    protected abstract bool Initialize();
    /// <summary>
    /// 外设内部单元初始化
    /// </summary>
    protected abstract void InitializeUnitList();

    /// <summary>
    /// 查找外设上的物理单元
    /// </summary>
    /// <typeparam name="T">物理单元类型</typeparam>
    /// <param name="unitID">单元ID</param>
    /// <returns></returns>
    public T Find<T>(string unitID) where T : PerpDevUnit {
        return this.mfPerpDevUnitList.Find(it => it.GetType().IsAssignableTo(typeof(T)) && it.UnitID == unitID) as T;
    }

    /// <summary>
    /// 查找指定类型的物理单元
    /// </summary>
    /// <typeparam name="T">物理单元类型</typeparam>
    /// <returns></returns>
    public IEnumerable<T> Unit<T>() where T : PerpDevUnit {
        return this.Unit(typeof(T)).Select(it => (T)it);
    }

    public IEnumerable<PerpDevUnit> Unit(Type typeInfo) {
        return this.mfPerpDevUnitList.Where(it => it.GetType().IsAssignableTo(typeInfo));
    }

    public IPerpDevConfig PerpDevConfig { get; protected set; }
    protected IPerpDevConfigRepository mfPerpDevConfigRepository;
    /// <summary>
    /// 设置外设对象配置仓储，外设对象利用仓储持久化自身配置
    /// </summary>
    /// <param name="perpDevConfigRepository">外设对象配置仓储</param>
    /// <returns></returns>
    public PerpDev CfgSet(IPerpDevConfigRepository perpDevConfigRepository, IPerpDevConfig perpDevConfig) {
        this.mfPerpDevConfigRepository = perpDevConfigRepository;
        this.PerpDevConfig = perpDevConfig;
        return this;
    }

}
